﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "SingleGrid.h"
#include "AlgorithmMinimalDistance.h"
#include "AlgorithmProject.h"
#include "AuxiliaryElementUtils.h"
#include "CurveEditUtils.h"
#include "DbObjectUtils.h"
#include "ElementId.h"
#include "GbmpBuiltInCategoryUniIdentitiesNew.h"
#include "GcmpBuiltInCategoryUniIdentities.h"
#include "GridNameManager.h"
#include "GridNewCommon.h"
#include "GridNewInput.h"
#include "GridNewUtils.h"
#include "IArc2d.h"
#include "ICurve2d.h"
#include "ICurve3d.h"
#include "IDocument.h"
#include "IElementBasicInformation.h"
#include "IElementModelShape.h"
#include "IElementOffsetComponent.h"
#include "IElementParameterBindings.h"
#include "IElementParameters.h"
#include "IElementParentReporter.h"
#include "IElementPosition.h"
#include "IElementShapeHandle.h"
#include "IElementStatus.h"
#include "IElementViewSpecificShapeComponent.h"
#include "IGenericElement.h"
#include "IGraphicsArc.h"
#include "IGraphicsBRepBody.h"
#include "IGraphicsCurve3d.h"
#include "IGraphicsElementShape.h"
#include "IGraphicsStyleManager.h"
#include "IGraphicsText.h"
#include "IJoinRelationshipBehavior.h"
#include "ILine2d.h"
#include "IModelView.h"
#include "IViewClipRange.h"
#include "IParameter.h"
#include "IParameterBinding.h"
#include "IParameterDefinitionLibrary.h"
#include "IParameterValueElementId.h"

#include "IPlane.h"
#include "IRegenerator.h"
#include "IRegeneratorDataIdCreator.h"
#include "SingleGridBehaviors.h"
#include "Vector3dUtils.h"
#include "IGeometryRelationshipComponent.h"
#include "ImplementationUidTreeRegister.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gcmp;



//EXPOSE_DEBUG_MODE_EXPORT(ReplaceBuiltInBehaviorWithNullPointer, GCMP_MODEL_EXPORT)
//EXPOSE_DEBUG_MODE_EXPORT(ReplaceBuiltInBehaviorWithNullBehavior, GCMP_MODEL_EXPORT)
EXPOSE_DEBUG_MODE(defRectViewPortChanged);
namespace
{
    // 获取轴网标签ElementShape
    gcmp::OwnerPtr<gcmp::IGraphicsElementShape> GetTagShape(
        const IPlane* pPlane,
        const Vector3d& point,
        const Vector3d& direction,
        const std::wstring& name,
        double scale)
    {
        OwnerPtr<IGraphicsElementShape> opRet = IGraphicsElementShape::Create(GraphicsRenderLayer::ReferenceObject);
        DBG_WARN_AND_RETURN_UNLESS(pPlane, opRet, L"pPlane为空。",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_UNLESS(!Vector3dUtils::IsParallel(pPlane->GetNormal(), direction), opRet, L"direction与pPlane的法向不能平行。",L"GDMPLab",L"2024-03-30");
        DBG_WARN_AND_RETURN_UNLESS(!MathUtils::IsZero(scale), opRet, L"scale不能为0。",L"GDMPLab",L"2024-03-30");

        // 轴号圆圈
        const double diameter = GridNewConstants::TAG_DIAMETER / scale;
        const double radius = diameter * 0.5;
        Vector3d dirX = direction;
        dirX.Normalize();
        Vector3d dirY = pPlane->GetNormal().Cross(dirX);
        dirY.Normalize();

        Vector2d uvParameter; Vector3d projectedPoint;
        bool bOk = AlgorithmProject::Project(point, pPlane, uvParameter, projectedPoint);
        DBG_WARN_AND_RETURN_UNLESS(bOk, opRet, L"point向plane投影失败。",L"GDMPLab",L"2024-03-30");

        Vector3d center = projectedPoint + dirX * radius;
        OwnerPtr<IGraphicsArc> opLeftArc = IGraphicsArc::CreateByCenterAndRadius(center, dirX, dirY, radius, 0.0, Constants::MATH_PI, true);
        opLeftArc->SetIsSnappable(false);
        opRet->AddChild(TransferOwnership(opLeftArc));
        OwnerPtr<IGraphicsArc> opRightArc = IGraphicsArc::CreateByCenterAndRadius(center, dirX, dirY, radius, 0.0, Constants::MATH_PI, false);
        opRightArc->SetIsSnappable(false);
        opRet->AddChild(TransferOwnership(opRightArc));

        // 轴号文字
        const float textHeight = static_cast<float>(GridNewConstants::TAG_TEXT_HEIGHT / scale);
        OwnerPtr<IGraphicsText> opNameLabel = IGraphicsText::Create(L"", center, pPlane->GetDirectionU(), pPlane->GetNormal(), textHeight, name.c_str(), AnchorAlignmentType::BottomCenter);
        opNameLabel->SetAnchorAlignment(gcmp::AnchorAlignmentType::Center);
        opNameLabel->SetIsSnappable(false);
        opRet->AddChild(TransferOwnership(opNameLabel));

        return opRet;
    }
}

DBOBJECT_DATA_DEFINE(SingleGrid)
{
    m_pOwnerElement = nullptr;
}
IMPLEMENT_REGEN_FUNCTIONS(gcmp, SingleGrid, SurfaceAndTerminals)
IMPLEMENT_REGEN_FUNCTIONS(gcmp, SingleGrid, Leaders)

#pragma region 基本属性


gcmp::NdbObject* gcmp::SingleGrid::GetTopOwnerObject() const
{
    return quick_cast<NdbObject>(const_cast<IElement*>(GetOwnerElement()));
}

IDocument * gcmp::SingleGrid::GetDocument() const
{
    if (!m_pOwnerElement)
    {
        return nullptr;
    }
    return m_pOwnerElement->GetDocument();
}

ElementId gcmp::SingleGrid::GetOwnerElementId() const
{
    if (!m_pOwnerElement)
    {
        return ElementId::InvalidID;
    }
    return m_pOwnerElement->GetElementId();
}


bool SingleGrid::SetOwnerElement(IElement* pOwnerElement)
{
    m_pOwnerElement = pOwnerElement;
    return true;
}

#pragma endregion 基本属性

#pragma region 关联更新

void gcmp::SingleGrid::UpdateForWeakParentDeletion(const std::set<ElementId>& deletedElementIds)
{
    IElement* pElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"IElement为空",L"GDMPLab",L"2024-03-30");

    //参数绑定，并且绑定的不是族参数时
    IElementParameterBindings* pBehavior = GetOwnerElement()->GetElementParameters()->GetElementParameterBindings();
    if (pBehavior)
    {
        auto& bindingInfos = pBehavior->GetParameterBindings();
        for (int ii = (int)bindingInfos.size(); ii > 0; --ii)
        {
            const IParameterBinding* info = bindingInfos[ii - 1].get();
            IElement* pSourceElement = GetDocument()->GetElement(info->GetSourceElementId());
            if (pSourceElement == nullptr)
            {
                continue;
            }

            IElementParameterBindings* pBingBehavior = pSourceElement->GetElementParameters()->GetElementParameterBindings();
            DBG_WARN_AND_RETURN_VOID_UNLESS(pBingBehavior, L"pBingBehavior无效",L"GDMPLab",L"2024-03-30");

            std::vector<RegenDataId> rcDataIds = pBingBehavior->GetParameterRdIdsByParameterDefinitionId(info->GetSourceParameterDefinitionId());
            std::size_t size = rcDataIds.size();
            if (size > 0 && size != 2) // IFamilyManager为2
            {
                if (deletedElementIds.find(info->GetSourceElementId()) != deletedElementIds.end())
                {
                    pBehavior->DeleteParameterBinding(info->GetTargetParameterDefinitionId());
                }
            }
        }
    }
    }

void gcmp::SingleGrid::ReportParents(IElementParentReporter& reporter) const
{
    const IElement* pElement = GetOwnerElement();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pElement, L"IElement为空",L"GDMPLab",L"2024-03-30");
    const IElementPosition *posBehavior = pElement->GetElementPosition();
    if (posBehavior != nullptr)
    {
        reporter.ReportStrong(posBehavior->GetBaseAssociatedPlaneId());
    }

    const IGeometryRelationshipComponent* pGeometryRepCpt = pElement->GetGeometryRelationshipComponent();
    if (pGeometryRepCpt)
    {
        const IJoinRelationshipBehavior*pJoineHelper = pGeometryRepCpt->GetJoinRelationship();
        if (pJoineHelper != nullptr)
        {
            reporter.ReportWeak(pJoineHelper->GetElementJoinIdsAtStart());
            reporter.ReportWeak(pJoineHelper->GetElementJoinIdsAtEnd());
            reporter.ReportWeak(pJoineHelper->GetElementJoinIdsAtMiddle());
        }
    }

    const IElementParameterBindings* pBehavior = GetOwnerElement()->GetElementParameters()->GetElementParameterBindings();
    if (pBehavior)
    {
        auto& bindingInfos = pBehavior->GetParameterBindings();
        FOR_EACH(info, bindingInfos)
        {
            IElement* pSourceElement = GetDocument()->GetElement(info->GetSourceElementId());
            if (pSourceElement != nullptr)
            {
                reporter.ReportWeak(pSourceElement->GetElementId());
            }
        }
    }

    auto& embeddedParamMap = GetOwnerElement()->GetElementParameters()->GetEmbeddedParametersMap();
    FOR_EACH(iter, embeddedParamMap)
    {
        const IParameterValueElementId *pElementIdParamValue = dynamic_cast<const IParameterValueElementId *>(iter.second->GetParameterValueStorage());
        if (pElementIdParamValue != nullptr)
        {
            reporter.ReportWeak(pElementIdParamValue->GetValue());
        }
    }

    reporter.ReportStrong(GetOwnerElement()->GetBasicInformation()->GetTypeId());

    const IGraphicsElementShape* pGrep = pElement->GetElementModelShape()->GetGraphicsElementShape();
    if (pGrep)
    {
        std::vector<ElementId> ids;
        pGrep->GetReferencedElementIds(ids);
        reporter.ReportWeak(ids);
    }

}

#pragma endregion 关联更新

#pragma region 其他
bool gcmp::SingleGrid::FinishEditing()
{
    std::vector<ElementId> ids = AuxiliaryElementUtils::GetAuxiliaryElements(GetOwnerElement());
    for (int i = 0; i < (int)ids.size(); i++)
    {
        IElement* pElement = GetDocument()->GetElement(ids[i]);
        IElementShapeHandle* pElementShapeHandle = quick_cast<IElementShapeHandle>(pElement);
        if (pElementShapeHandle)
        {
            pElementShapeHandle->FinishEditing();
            continue;
        }
    }
    return true;
}

#pragma endregion 其他


gcmp::IGridNew* gcmp::SingleGrid::Create(const GridNewInput& gridNewInput)
{
    //检查GridNewInput输入是否合法
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(gridNewInput.Document, L"Document为空",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(gridNewInput.VecOpCurve.size()!= 0, L"VecOpCurve为空",L"GDMPLab",L"2024-03-30");
    IGridNew *pGrid = nullptr;
    if (gridNewInput.VecOpCurve.size() == 1)
    {
        const ICurve2d * pCurve2d = gridNewInput.VecOpCurve[0].get();
        if (const ILine2d* curve2d = (quick_cast<ILine2d>(pCurve2d)))
        {
            pGrid = CreateAsLine(gridNewInput.Document, curve2d, gridNewInput.verticalExtents, gridNewInput.CreationOption);
        }
        else if (const IArc2d* curve2d = (quick_cast<IArc2d>(pCurve2d)))
        {
            pGrid = CreateAsArc(gridNewInput.Document, curve2d, gridNewInput.verticalExtents, gridNewInput.CreationOption);
        }
        else
        {
            DBG_WARN_AND_RETURN_NULLPTR_UNLESS(false, L"gridNewInput的线型不是直线段或者圆弧线段",L"GDMPLab",L"2024-03-30");
        }
    }
    else
    {
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(false, L"目前不支持多端轴网",L"GDMPLab",L"2024-03-30");
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGrid, L"pPresetGrid为空",L"GDMPLab",L"2024-03-30");
    IElement* pElement = pGrid->GetOwnerElement();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pElement, L"pPresetGrid为空",L"GDMPLab",L"2024-03-30");
    // 预设轴网设置隐藏
    pElement->GetStatus()->SetIsVisible(gridNewInput.Visible);

    //根据GridNewInput信息设置名字
    if (!gridNewInput.GridNewName.empty())
    {
        pGrid->SetName(gridNewInput.GridNewName);
    }
    else
    {
        pGrid->AutoName();
    }

    // 设置起终点标识可见性
    pGrid->SetStartTagVisibleInPlanView(gridNewInput.StartTagVisble);
    pGrid->SetEndTagVisibleInPlanView(gridNewInput.EndTagVisble);
    return pGrid;
}

gcmp::IGridNew* gcmp::SingleGrid::CreateAsEmpty(IDocument* pDoc, ElementCreationOptions eco /*= ElementCreationOptions::Normal*/)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"invalid params",L"GDMPLab",L"2024-03-30");
    OwnerPtr<SingleGrid> opGrid = NEW_AS_OWNER_PTR(SingleGrid);
    SingleGrid* pGrid = opGrid.get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGrid, L"pGrid为空",L"GDMPLab",L"2024-03-30");

    IGenericElement* pGenericElement = IGenericElement::Create(pDoc, TransferOwnership(opGrid), SingleGrid::GetClassId().GetGuid(), eco);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pGenericElement, L"pGenericElement为空",L"GDMPLab",L"2024-03-30");
    pGenericElement->GetBasicInformation()->SetCategoryUid(BuiltInCategoryUniIdentities::BICU_NEW_GRID);
    pGenericElement->GetBasicInformation()->SetDefaultTypeName(GBMP_TR(L"轴网"));
    pGenericElement->GetBasicInformation()->SetImplementationUid(SingleGrid::GetImplementationUid());

    pGenericElement->SetElementCopyPasteComponent(NEW_AS_OWNER_PTR(SingleGridCopyPasteComponent));
    if (pGenericElement->GetElementParameters())
        pGenericElement->GetElementParameters()->SetElementParametersCustomizer(NEW_AS_OWNER_PTR(SingleGridParametersCustomizer));
    pGenericElement->SetElementTransformationComponent(NEW_AS_OWNER_PTR(SingleGridTransformationComponent));
    pGenericElement->SetViewSpecificShapeComponent(NEW_AS_OWNER_PTR(SingleGridViewSpecificShapeComponent));

    pGrid->SetStartTagVisible__(false);
    pGrid->SetEndTagVisible__(true);
    return quick_cast<SingleGrid>(pGenericElement->GetExternalObject());
}

gcmp::IGridNew* gcmp::SingleGrid::CreateAsLine(
    IDocument* pDoc, 
    const ILine2d* pLine2d, 
    const Intervald& verticalExtents, 
    ElementCreationOptions eco /*= ElementCreationOptions::Normal*/)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc && pLine2d && !verticalExtents.IsEmpty(), L"invalid params",L"GDMPLab",L"2024-03-30");
    IGridNew* pGrid = CreateAsEmpty(pDoc, eco);
    pGrid->SetHorizontalGridCurves({ pLine2d });
    pGrid->SetVerticalExtents(verticalExtents);
    pGrid->FinishEditing();
    return pGrid;
}

gcmp::IGridNew* gcmp::SingleGrid::CreateAsArc(
    IDocument* pDoc, 
    const IArc2d* pArc2d, 
    const Intervald& verticalExtents, 
    ElementCreationOptions eco /*= ElementCreationOptions::Normal*/)
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc && pArc2d && !verticalExtents.IsEmpty(), L"invalid params",L"GDMPLab",L"2024-03-30");
    IGridNew* pGrid = CreateAsEmpty(pDoc, eco);
    pGrid->SetHorizontalGridCurves({ pArc2d });
    pGrid->SetVerticalExtents(verticalExtents);
    pGrid->FinishEditing();
    return pGrid;
}

#pragma region IGridNew接口

std::vector<gcmp::OwnerPtr<gcmp::ISurface>> gcmp::SingleGrid::GetGridSurfaces(ElementId modelviewId /*= ElementId::InvalidID*/) const
{
    std::vector<OwnerPtr<ISurface>> ret;
    const SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminals__().get();
    DBG_WARN_AND_RETURN_UNLESS(pSurfaceAndTerminals, ret, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");
    if (pSurfaceAndTerminals->HasLocalTerminalParams(modelviewId))
    {
        ret.push_back(pSurfaceAndTerminals->GetLocalSurface(modelviewId));
    }
    else
    {
        ret.push_back(pSurfaceAndTerminals->GetGlobalSurface());
    }

    return ret;
}

std::vector<gcmp::OwnerPtr<gcmp::ICurve3d>> gcmp::SingleGrid::GetHorizontalGridCurves(ElementId modelviewId /*= ElementId::InvalidID*/) const
{
    std::vector<gcmp::OwnerPtr<gcmp::ICurve3d>> ret;
    std::vector<OwnerPtr<ISurface>> surfaces = this->GetGridSurfaces(modelviewId);
    DBG_WARN_AND_RETURN_UNLESS(!surfaces.empty(), ret, L"surfaces为空。",L"GDMPLab",L"2024-03-30");
    const ISurface* pGridSurface = surfaces.front().get();
    DBG_WARN_AND_RETURN_UNLESS(pGridSurface, ret, L"pGridSurface为空。",L"GDMPLab",L"2024-03-30");

    // 等V线
    ret.push_back(pGridSurface->CreateVIsoParamCurve(pGridSurface->GetLimitV().Middle()));

    return ret;
}

gcmp::OwnerPtr<gcmp::ICurve3d> gcmp::SingleGrid::GetVerticalGridCurve(ElementId modelviewId /*= ElementId::InvalidID*/) const
{
    OwnerPtr<gcmp::ICurve3d> ret = nullptr;
    std::vector<OwnerPtr<ISurface>> surfaces = this->GetGridSurfaces(modelviewId);
    DBG_WARN_AND_RETURN_UNLESS(!surfaces.empty(), ret, L"surfaces为空。",L"GDMPLab",L"2024-03-30");
    const ISurface* pGridSurface = surfaces.front().get();
    DBG_WARN_AND_RETURN_UNLESS(pGridSurface, ret, L"pGridSurface为空。",L"GDMPLab",L"2024-03-30");

    // 等U线
    ret = pGridSurface->CreateUIsoParamCurve(pGridSurface->GetLimitU().Middle());

    return ret;
}

gcmp::Vector3d gcmp::SingleGrid::GetVerticalDirection() const
{
    return Vector3d::UnitZ;
}

bool gcmp::SingleGrid::SetHorizontalGridCurves(const std::vector<const ICurve2d*>& curves)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(1 == static_cast<int>(curves.size()), L"SingleGrid仅支持设置一段Curve。",L"GDMPLab",L"2024-03-30");

    if (this->GetSurfaceAndTerminals__())
    {
        Intervald verticalExtends = this->GetVerticalExtends(ElementId::InvalidID); // 获取全局VerticalExtends
        this->SetSurfaceAndTerminals__(SurfaceAndTerminals::Create(curves.front(), verticalExtends));
    }
    else
    {
        this->SetSurfaceAndTerminals__(SurfaceAndTerminals::Create(curves.front(), GridNewConstants::DEFAULT_VERTICAL_EXTENTS));
    }

    return true;
}

bool gcmp::SingleGrid::SetVerticalExtents(const Intervald& extents, ElementId modelviewId/* = ElementId::InvalidID*/)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(!extents.IsEmpty(), L"extends为空。",L"GDMPLab",L"2024-03-30");
    SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminalsFW__().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSurfaceAndTerminals, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");

    if (pSurfaceAndTerminals->HasLocalTerminalParams(modelviewId))
    {
        TerminalParams params = pSurfaceAndTerminals->GetLocalTerminalParams(modelviewId);
        params.SetStartRangeV(extents.GetMin());
        params.SetEndRangeV(extents.GetMax());
        pSurfaceAndTerminals->AddOrUpdateLocalTerminalParams(modelviewId, params);
    }
    else
    {
        TerminalParams params = pSurfaceAndTerminals->GetGlobalTerminalParams();
        params.SetStartRangeV(extents.GetMin());
        params.SetEndRangeV(extents.GetMax());
        pSurfaceAndTerminals->SetGlobalTerminalParams(params);
    }

    return true;
}

gcmp::OwnerPtr<gcmp::IGraphicsElementShape> gcmp::SingleGrid::CreateElementShapeBasedOnPlane(const IPlane* pPlane, double scale, const IModelView* pModelView) const
{
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pPlane, L"pPlane为空。",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"pModelView为空。",L"GDMPLab",L"2024-03-30");
    const std::wstring& strName = this->GetOwnerElement()->GetBasicInformation()->GetName();

    OwnerPtr<IGraphicsElementShape> opRet = IGraphicsElementShape::Create(GraphicsRenderLayer::ReferenceObject);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opRet, L"opRet为空。",L"GDMPLab",L"2024-03-30");

    if (DEBUG_MODE(defRectViewPortChanged))
        opRet->SetIsClippable(false);

    // 输入平面是水平面
    if (Vector3dUtils::IsParallel(pPlane->GetNormal(), Vector3d::UnitZ))
    {
        std::vector<OwnerPtr<ICurve3d>> curves = this->GetHorizontalGridCurves();
        Vector3d retPos = Vector3d();
        Vector3d projectPoint = Vector3d();
        FOR_EACH(opCurve, curves)
        {
            DBG_WARN_AND_CONTINUE_UNLESS(opCurve, L"opCurve为空",L"GDMPLab",L"2024-03-30");
            OwnerPtr<ICurve3d> opResCurve = AlgorithmProject::ProjectReturnCurve3d(opCurve.get(), pPlane);
            DBG_WARN_AND_CONTINUE_UNLESS(opResCurve, L"opResCurve为空",L"GDMPLab",L"2024-03-30");
            if (DEBUG_MODE(defRectViewPortChanged))
            {
                if (pModelView->IsCroppedByViewport())
                {
                    double leftOffset = 0.0;
                    double rightOffset = 0.0;
                    double upOffset = 0.0;
                    double downOffset = 0.0;
                    IViewClipRange* pViewClipRange = IViewClipRange::GetViewClipRange(pModelView->GetDocument(), pModelView->GetViewClipRangeId());
                    pViewClipRange->GetRectViewClipRange(leftOffset, rightOffset, upOffset, downOffset);
                    Vector3d origin = pModelView->GetOrigin();
                    Vector3d dirRight = pModelView->GetRightDirection();
                    dirRight.Normalize();
                    Vector3d dirUp = pModelView->GetUpDirection();
                    dirUp.Normalize();
                    // 获得裁剪框右夹点的坐标
                    retPos = origin + dirRight * rightOffset + dirUp * (upOffset - downOffset) * 0.5;
                    if (retPos.GetX() < opResCurve->GetEndPoint().GetX() && retPos.GetX() > opResCurve->GetStartPoint().GetX())
                    {
                        // 裁剪框夹点在轴网上的投影
                        double dParameter = 0.0;
                        AlgorithmProject::Project(retPos, quick_cast<ILine3d>(opResCurve.get()), dParameter, projectPoint);
                        double startParameter = opResCurve->GetStartLimit();
                        // 修改轴网的长度
                        opResCurve->SetLimits(Intervald(startParameter, dParameter));
                    }
                }
            }
            
            OwnerPtr<IGraphicsCurve3d> opGraphicsCurve = IGraphicsCurve3d::Create(opResCurve.get());
            DBG_WARN_AND_CONTINUE_UNLESS(opGraphicsCurve, L"opGraphicsCurve为空",L"GDMPLab",L"2024-03-30");
            opGraphicsCurve->SetGraphicsStyleId(GetDocument()->GetGraphicsStyleManager()->GetGraphicsStyleIdByCategoryUid(BuiltInCategoryUniIdentities::BICU_NEW_GRID));
            opRet->AddChild(TransferOwnership(opGraphicsCurve));
        }

        if (!curves.empty())
        {
            if (this->GetStartTagVisible__())
            {
                const ICurve3d* pFirstCurve = curves.front().get();
                if (pFirstCurve)
                {
                    OwnerPtr<IGraphicsElementShape> opBubble = GetTagShape(
                        pPlane, pFirstCurve->GetStartPoint(), -pFirstCurve->GetStartTangent(), strName, scale);
                    opBubble->SetIsSnappable(false);
                    opBubble->SetGraphicsStyleId(GetDocument()->GetGraphicsStyleManager()->GetGraphicsStyleIdByCategoryUid(BuiltInCategoryUniIdentities::BICU_NEW_GRID_TAG));
                    opRet->AddChild(TransferOwnership(opBubble));
                }
            }

            if (this->GetEndTagVisible__())
            {
                const ICurve3d* pLastCurve = curves.back().get();
                if (pLastCurve)
                {
                    Vector3d refPoint = pLastCurve->GetEndPoint();
                    if (DEBUG_MODE(defRectViewPortChanged) && pModelView->IsCroppedByViewport() && 
                        (retPos.GetX() < pLastCurve->GetEndPoint().GetX() && retPos.GetX() > pLastCurve->GetStartPoint().GetX()))
                            refPoint = projectPoint;
                    
                    OwnerPtr<IGraphicsElementShape> opBubble = GetTagShape(
                        pPlane, refPoint, pLastCurve->GetEndTangent(), strName, scale);
                    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opBubble, L"opBubble为空",L"GDMPLab",L"2024-03-30");
                    opBubble->SetIsSnappable(false);
                    opBubble->SetGraphicsStyleId(GetDocument()->GetGraphicsStyleManager()->GetGraphicsStyleIdByCategoryUid(BuiltInCategoryUniIdentities::BICU_NEW_GRID_TAG));
                    opRet->AddChild(TransferOwnership(opBubble));
                }
            }
        }
    }
    // 输入平面是竖直面
    else if (Vector3dUtils::IsPerpendicular(pPlane->GetNormal(), Vector3d::UnitZ))
    {
        OwnerPtr<ICurve3d> opCurve = this->GetVerticalGridCurve();
        if (opCurve)
        {
            OwnerPtr<ICurve3d> opResCurve = AlgorithmProject::ProjectReturnCurve3d(opCurve.get(), pPlane);
            OwnerPtr<IGraphicsCurve3d> opGraphicsCurve = IGraphicsCurve3d::Create(opResCurve.get());
            opGraphicsCurve->SetGraphicsStyleId(GetDocument()->GetGraphicsStyleManager()->GetGraphicsStyleIdByCategoryUid(BuiltInCategoryUniIdentities::BICU_NEW_GRID));
            opRet->AddChild(TransferOwnership(opGraphicsCurve));

            if (MathUtils::IsLessThan(opResCurve->GetStartPoint().GetZ(), opResCurve->GetEndPoint().GetZ()))
            {
                OwnerPtr<IGraphicsElementShape> opBubble = GetTagShape(
                    pPlane, opResCurve->GetStartPoint(), -opResCurve->GetStartTangent(), strName, scale);
                opBubble->SetIsSnappable(false);
                opBubble->SetGraphicsStyleId(GetDocument()->GetGraphicsStyleManager()->GetGraphicsStyleIdByCategoryUid(BuiltInCategoryUniIdentities::BICU_NEW_GRID_TAG));
                opRet->AddChild(TransferOwnership(opBubble));
            }
            else if (MathUtils::IsGreaterThan(opResCurve->GetStartPoint().GetZ(), opResCurve->GetEndPoint().GetZ()))
            {
                OwnerPtr<IGraphicsElementShape> opBubble = GetTagShape(
                    pPlane, opResCurve->GetEndPoint(), opResCurve->GetEndTangent(), strName, scale);
                opBubble->SetIsSnappable(false);
                opBubble->SetGraphicsStyleId(GetDocument()->GetGraphicsStyleManager()->GetGraphicsStyleIdByCategoryUid(BuiltInCategoryUniIdentities::BICU_NEW_GRID_TAG));
                opRet->AddChild(TransferOwnership(opBubble));
            }
        }
    }

    return opRet;
}

std::wstring gcmp::SingleGrid::GetName() const
{
    return GetOwnerElement()->GetBasicInformation()->GetName();
}

bool gcmp::SingleGrid::SetName(const std::wstring& name, std::wstring* errorMessage /*= nullptr*/)
{
    // TODO: gcmp中ElementParameterBehavior::SetParameter() 强行设置了名字参数行为，导致此处的检测不生效；后续需要跟踪

    //bool isNameValid = GridNewUtils::IsNameValid(name);
    //if (!isNameValid)
    //{
    //    std::wstring msg = GBMP_TR(L"轴网编号不能为以下特殊字符") + L"\n" + GridNewConstants::INVALID_NAME_CHARSET + L"\n" + GBMP_TR(L"也不能包含任何不可打印字符。");
    //    SAFE_INIT_POINTER(errorMessage, msg);
    //    return false;
    //}
    if (name == GetName())
    {
        return true;
    }

    bool isNameDuplicated = GridNewUtils::IsNameDuplicated(this->GetDocument(), name);
    if (isNameDuplicated)
    {
        std::wstring msg = GBMP_TR(L"所输入的名称已经使用。请输入唯一的名称。");
        SAFE_INIT_POINTER(errorMessage, msg);
        return false;
    }

    if (false == this->GetOwnerElement()->GetBasicInformation()->GetIsTransient())
    {
        // 若不是临时对象，则将可推断的编号记录为最后一个活动轴网编号；不可推断的编号不记录。
        std::wstring nextName;
        bool isNameDeducable = GridNewUtils::GetNextName(name, nextName);
        if (isNameDeducable)
        {
            GridNameManager::SetLastActiveName(this->GetDocument(), name);
        }
    }

    return GetOwnerElement()->GetBasicInformation()->SetName(name);
}

#pragma endregion IGridNew接口
 
bool gcmp::SingleGrid::IsHorizontalStraight() const
{
    const SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminals__().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSurfaceAndTerminals, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");
    return pSurfaceAndTerminals->IsPlanar();
}

bool gcmp::SingleGrid::IsHorizontalArc() const
{
    const SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminals__().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSurfaceAndTerminals, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");
    return pSurfaceAndTerminals->IsCylindric();
}

gcmp::Vector3d gcmp::SingleGrid::GetHorizontalStartPoint(ElementId modelviewId/* = ElementId::InvalidID*/) const
{
    return this->GetTerminalPoint(TT_Start, TT_Start, modelviewId);
}

bool gcmp::SingleGrid::SetHorizontalStartPoint(const Vector3d& point, ElementId modelviewId/* = ElementId::InvalidID*/)
{
    SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminalsFW__().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSurfaceAndTerminals, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");
    const ISurface* pDatumSurface = pSurfaceAndTerminals->GetSurfaceReference();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDatumSurface, L"pDatumSurface为空。",L"GDMPLab",L"2024-03-30");

    std::vector<OwnerPtr<ICurve3d>> curves = this->GetHorizontalGridCurves(modelviewId);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(1 == static_cast<int>(curves.size()), L"surfaces应该只有1个元素",L"GDMPLab",L"2024-03-30");
    const ICurve3d* pCurve3d = curves.front().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCurve3d, L"pCurve3d为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IPlane> opPlane = IPlane::Create(Vector3d(0.0,0.0,0.0), Vector3d::UnitX, Vector3d::UnitY);
    OwnerPtr<ICurve2d> opCurve2d = AlgorithmProject::Project(pCurve3d, opPlane.get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(opCurve2d, L"opCurve2d为空",L"GDMPLab",L"2024-03-30");

    bool res = false;
    std::wstring errorMessage;
    if (ILine2d* pLine2d = quick_cast<ILine2d>(opCurve2d.get()))
    {
        res = CurveEditUtils::EditLine2dByPoint(pLine2d, PointTypeOnCurve::StartPoint, point.Vec2d(), errorMessage);
    }
    else if (IArc2d* pArc2d = quick_cast<IArc2d>(opCurve2d.get()))
    {
        res = CurveEditUtils::EditArc2dByPoint(pArc2d, PointTypeOnCurve::StartPoint, point.Vec2d(), errorMessage);
    }
    DBG_WARN_AND_RETURN_FALSE_UNLESS(res, L"编辑失败:\n" + errorMessage,L"GDMPLab",L"2024-03-30");
    this->EditAsHorizontalCurve(opCurve2d.get(), modelviewId);

    MarkSurfaceAndTerminalsRdId();
    return true;
}

gcmp::Vector3d gcmp::SingleGrid::GetHorizontalEndPoint(ElementId modelviewId/* = ElementId::InvalidID*/) const
{
    return this->GetTerminalPoint(TT_End, TT_End, modelviewId);
}

bool gcmp::SingleGrid::SetHorizontalEndPoint(const Vector3d& point, ElementId modelviewId/* = ElementId::InvalidID*/)
{
    SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminalsFW__().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSurfaceAndTerminals, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");
    const ISurface* pDatumSurface = pSurfaceAndTerminals->GetSurfaceReference();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDatumSurface, L"pDatumSurface为空。",L"GDMPLab",L"2024-03-30");

    std::vector<OwnerPtr<ICurve3d>> curves = this->GetHorizontalGridCurves(modelviewId);
    DBG_WARN_AND_RETURN_FALSE_UNLESS(1 == static_cast<int>(curves.size()), L"surfaces应该只有1个元素",L"GDMPLab",L"2024-03-30");
    const ICurve3d* pCurve3d = curves.front().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCurve3d, L"pCurve3d为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IPlane> opPlane = IPlane::Create(Vector3d(0.0, 0.0, 0.0), Vector3d::UnitX, Vector3d::UnitY);
    OwnerPtr<ICurve2d> opCurve2d = AlgorithmProject::Project(pCurve3d, opPlane.get());
    DBG_WARN_AND_RETURN_FALSE_UNLESS(opCurve2d, L"opCurve2d为空",L"GDMPLab",L"2024-03-30");

    bool res = false;
    std::wstring errorMessage;
    if (ILine2d* pLine2d = quick_cast<ILine2d>(opCurve2d.get()))
    {
        res = CurveEditUtils::EditLine2dByPoint(pLine2d, PointTypeOnCurve::EndPoint, point.Vec2d(), errorMessage);
    }
    else if (IArc2d* pArc2d = quick_cast<IArc2d>(opCurve2d.get()))
    {
        res = CurveEditUtils::EditArc2dByPoint(pArc2d, PointTypeOnCurve::EndPoint, point.Vec2d(), errorMessage);
    }
    DBG_WARN_AND_RETURN_FALSE_UNLESS(res, L"编辑失败",L"GDMPLab",L"2024-03-30");
    this->EditAsHorizontalCurve(opCurve2d.get(), modelviewId);

    MarkSurfaceAndTerminalsRdId();
    return true;
}

gcmp::Vector3d gcmp::SingleGrid::GetHorizontalStartTangent(ElementId modelviewId/* = ElementId::InvalidID*/) const
{
    std::vector<OwnerPtr<ICurve3d>> curves = this->GetHorizontalGridCurves(modelviewId);
    DBG_WARN_AND_RETURN_UNLESS(1 == static_cast<int>(curves.size()), Vector3d::Zero, L"单段轴网为何有多段线？",L"GDMPLab",L"2024-03-30");
    const ICurve3d* pGridCurve = curves.front().get();
    DBG_WARN_AND_RETURN_UNLESS(pGridCurve, Vector3d::Zero, L"pGridCurve为空。",L"GDMPLab",L"2024-03-30");
    return pGridCurve->GetStartTangent();
}

gcmp::Vector3d gcmp::SingleGrid::GetHorizontalEndTangent(ElementId modelviewId/* = ElementId::InvalidID*/) const
{
    std::vector<OwnerPtr<ICurve3d>> curves = this->GetHorizontalGridCurves(modelviewId);
    DBG_WARN_AND_RETURN_UNLESS(1 == static_cast<int>(curves.size()), Vector3d::Zero, L"单段轴网为何有多段线？",L"GDMPLab",L"2024-03-30");
    const ICurve3d* pGridCurve = curves.front().get();
    DBG_WARN_AND_RETURN_UNLESS(pGridCurve, Vector3d::Zero, L"pGridCurve为空。",L"GDMPLab",L"2024-03-30");
    return pGridCurve->GetEndTangent();
}

gcmp::Vector3d gcmp::SingleGrid::GetVerticalStartPoint(ElementId modelviewId /*= ElementId::InvalidID*/) const
{
    return this->GetTerminalPoint(TT_Start, TT_Start, modelviewId);
}

bool gcmp::SingleGrid::SetVerticalStartPoint(const Vector3d& point, ElementId modelviewId /*= ElementId::InvalidID*/)
{
    SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminalsFW__().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSurfaceAndTerminals, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");
    const ISurface* pDatumSurface = pSurfaceAndTerminals->GetSurfaceReference();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDatumSurface, L"pDatumSurface为空。",L"GDMPLab",L"2024-03-30");

    Vector3d minimalDistancePointOnSurface;
    Vector2d paramOnSurface;
    double minDistance = 0.0;
    bool success = AlgorithmMinimalDistance::Calculate(pDatumSurface, point, minimalDistancePointOnSurface, false, &paramOnSurface, minDistance);
    if (!success)
        return false;

    if (pSurfaceAndTerminals->HasLocalTerminalParams(modelviewId))
    {
        TerminalParams params = pSurfaceAndTerminals->GetLocalTerminalParams(modelviewId);
        params.SetStartRangeV(paramOnSurface.GetY());
        pSurfaceAndTerminals->AddOrUpdateLocalTerminalParams(modelviewId, params);
    }
    else
    {
        TerminalParams params = pSurfaceAndTerminals->GetGlobalTerminalParams();
        params.SetStartRangeV(paramOnSurface.GetY());
        pSurfaceAndTerminals->SetGlobalTerminalParams(params);
    }

    MarkSurfaceAndTerminalsRdId();
    return true;
}

gcmp::Vector3d gcmp::SingleGrid::GetVerticalEndPoint(ElementId modelviewId /*= ElementId::InvalidID*/) const
{
    return this->GetTerminalPoint(TT_End, TT_End, modelviewId);
}

bool gcmp::SingleGrid::SetVerticalEndPoint(const Vector3d& point, ElementId modelviewId /*= ElementId::InvalidID*/)
{
    SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminalsFW__().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSurfaceAndTerminals, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");
    const ISurface* pDatumSurface = pSurfaceAndTerminals->GetSurfaceReference();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDatumSurface, L"pDatumSurface为空。",L"GDMPLab",L"2024-03-30");

    Vector3d minimalDistancePointOnSurface;
    Vector2d paramOnSurface;
    double minDistance = 0.0;
    bool success = AlgorithmMinimalDistance::Calculate(pDatumSurface, point, minimalDistancePointOnSurface, false, &paramOnSurface, minDistance);
    if (!success)
        return false;

    if (pSurfaceAndTerminals->HasLocalTerminalParams(modelviewId))
    {
        TerminalParams params = pSurfaceAndTerminals->GetLocalTerminalParams(modelviewId);
        params.SetEndRangeV(paramOnSurface.GetY());
        pSurfaceAndTerminals->AddOrUpdateLocalTerminalParams(modelviewId, params);
    }
    else
    {
        TerminalParams params = pSurfaceAndTerminals->GetGlobalTerminalParams();
        params.SetEndRangeV(paramOnSurface.GetY());
        pSurfaceAndTerminals->SetGlobalTerminalParams(params);
    }

    MarkSurfaceAndTerminalsRdId();
    return true;
}

gcmp::Vector3d gcmp::SingleGrid::GetVerticalStartTangent(ElementId modelviewId /*= ElementId::InvalidID*/) const
{
    OwnerPtr<ICurve3d> opCurve = this->GetVerticalGridCurve(modelviewId);
    const ICurve3d* pGridCurve = opCurve.get();
    DBG_WARN_AND_RETURN_UNLESS(pGridCurve, Vector3d::Zero, L"pGridCurve为空。",L"GDMPLab",L"2024-03-30");
    return pGridCurve->GetStartTangent();
}

gcmp::Vector3d gcmp::SingleGrid::GetVerticalEndTangent(ElementId modelviewId /*= ElementId::InvalidID*/) const
{
    OwnerPtr<ICurve3d> opCurve = this->GetVerticalGridCurve(modelviewId);
    const ICurve3d* pGridCurve = opCurve.get();
    DBG_WARN_AND_RETURN_UNLESS(pGridCurve, Vector3d::Zero, L"pGridCurve为空。",L"GDMPLab",L"2024-03-30");
    return pGridCurve->GetEndTangent();
}

gcmp::Intervald gcmp::SingleGrid::GetVerticalExtends(ElementId modelviewId/* = ElementId::InvalidID*/) const
{
    const SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminals__().get();
    DBG_WARN_AND_RETURN_UNLESS(pSurfaceAndTerminals, Intervald::CreateEmptyIntervald(), L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");

    Intervald ret;
    bool bSameDirV = false;
    if (pSurfaceAndTerminals->HasLocalTerminalParams(modelviewId))
    {
        const TerminalParams params = pSurfaceAndTerminals->GetLocalTerminalParams(modelviewId);
        ret = params.GetRangeV(bSameDirV);
    }
    else
    {
        const TerminalParams params = pSurfaceAndTerminals->GetGlobalTerminalParams();
        ret = params.GetRangeV(bSameDirV);
    }

    return ret;
}

bool gcmp::SingleGrid::IsOverridedByAnyModelView() const
{
    const SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminals__().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSurfaceAndTerminals, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");
    return pSurfaceAndTerminals->HasLocalTerminalParams();
}

bool gcmp::SingleGrid::ClearModelViewOverridedParams()
{
    SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminalsFW__().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSurfaceAndTerminals, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");
    pSurfaceAndTerminals->DeleteAllLocalTerminalParams();
    MarkSurfaceAndTerminalsRdId();
    return true;
}

bool gcmp::SingleGrid::Transform(const Matrix4d& mat)
{
    SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminalsFW__().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSurfaceAndTerminals, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");
    pSurfaceAndTerminals->PerformTranform(mat);
    MarkSurfaceAndTerminalsRdId();
    return true;
}


gcmp::UniIdentity gcmp::SingleGrid::GetImplementationUid()
{
    static UniIdentity s_implementationUid = UniIdentity::Create(
        GuidUtils::FromString(L"{90EE4762-D303-4868-81BC-67BD989676D5}"), L"SingleGrid");
    return s_implementationUid;
}

bool gcmp::SingleGrid::AutoName()
{
    if (GridNameManager::IsNameInitialized(this->GetDocument()))
    {
        // 根据最后一个活动轴网编号，自动推断下一个编号
        std::wstring currName = GridNameManager::GetLastActiveName(this->GetDocument());
        std::wstring nextName;
        bool isNameDeducable = GridNewUtils::GetNextName(currName, nextName);
        DBG_WARN_UNLESS(isNameDeducable, L"自动生成了不可推断的轴网名称",L"GDMPLab",L"2024-03-30");

        // 若编号被占用，则再继续推断，直到推断出一个未被占用的编号为止
        while (GridNewUtils::IsNameDuplicated(this->GetDocument(), nextName))
        {
            currName = nextName;
            isNameDeducable = GridNewUtils::GetNextName(currName, nextName);
            DBG_WARN_AND_BREAK_UNLESS(isNameDeducable, L"自动生成了不可推断的轴网名称",L"GDMPLab",L"2024-03-30");
        }

        if (isNameDeducable)
        {
            this->GetOwnerElement()->GetBasicInformation()->SetName(nextName);
        }
    }
    else
    {
        // 若轴网编号管理未被初始化，则使用默认初始编号
        this->GetOwnerElement()->GetBasicInformation()->SetName(GridNewConstants::DEFAULT_NAME);
    }

    if (false == this->GetOwnerElement()->GetBasicInformation()->GetIsTransient())
    {
        // 若不是临时对象，则将可推断的编号记录为最后一个活动轴网编号
        std::wstring currName = this->GetOwnerElement()->GetBasicInformation()->GetName();
        std::wstring nextName;
        bool isNameDeducable = GridNewUtils::GetNextName(this->GetOwnerElement()->GetBasicInformation()->GetName(), nextName);
        if (isNameDeducable)
        {
            GridNameManager::SetLastActiveName(this->GetDocument(), this->GetOwnerElement()->GetBasicInformation()->GetName());
        }
    }

    return true;
}

gcmp::Vector3d gcmp::SingleGrid::GetTerminalPoint(
    EnTerminalType uTerminalType, 
    EnTerminalType vTerminalType, 
    ElementId modelviewId /*= ElementId::InvalidID*/) const
{
    const SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminals__().get();
    DBG_WARN_AND_RETURN_UNLESS(pSurfaceAndTerminals, Vector3d::Zero, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");
    const ISurface* pDatumSurface = pSurfaceAndTerminals->GetSurfaceReference();
    DBG_WARN_AND_RETURN_UNLESS(pDatumSurface, Vector3d::Zero, L"pDatumSurface为空。",L"GDMPLab",L"2024-03-30");

    TerminalParams params;
    if (pSurfaceAndTerminals->HasLocalTerminalParams(modelviewId))
    {
        params = pSurfaceAndTerminals->GetLocalTerminalParams(modelviewId);
    }
    else
    {
        params = pSurfaceAndTerminals->GetGlobalTerminalParams();
    }

    double paramU = 0.0;
    switch (uTerminalType)
    {
    case gcmp::SingleGrid::TT_Start:
        paramU = params.GetStartRangeU();
        break;
    case gcmp::SingleGrid::TT_End:
        paramU = params.GetEndRangeU();
        break;
    }

    double paramV = 0.0;
    switch (vTerminalType)
    {
    case gcmp::SingleGrid::TT_Start:
        paramV = params.GetStartRangeV();
        break;
    case gcmp::SingleGrid::TT_End:
        paramV = params.GetEndRangeV();
        break;
    }

    Vector3d point3d = pDatumSurface->GetPoint(paramU, paramV);
    return point3d;
}

bool gcmp::SingleGrid::EditAsHorizontalCurve(const ICurve2d* pCurve2d, ElementId modelviewId)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pCurve2d, L"pCurve2d为空。",L"GDMPLab",L"2024-03-30");
    SurfaceAndTerminals* pSurfaceAndTerminals = this->GetSurfaceAndTerminalsFW__().get();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pSurfaceAndTerminals, L"pSurfaceAndTerminals为空。",L"GDMPLab",L"2024-03-30");
    const ISurface* pDatumSurface = pSurfaceAndTerminals->GetSurfaceReference();
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pDatumSurface, L"pDatumSurface为空。",L"GDMPLab",L"2024-03-30");

    Vector3d startPt, midPt, endPt;
    Vector2d startParam, midParam, endParam;
    double startMinDistance, midMinDistance, endMinDistance;
    bool success1 = AlgorithmMinimalDistance::Calculate(pDatumSurface, Vector3d(pCurve2d->GetStartPoint(), 0), startPt, false, &startParam, startMinDistance);
    bool success2 = AlgorithmMinimalDistance::Calculate(pDatumSurface, Vector3d(pCurve2d->GetMiddlePoint(), 0), midPt, false, &midParam, midMinDistance);
    bool success3 = AlgorithmMinimalDistance::Calculate(pDatumSurface, Vector3d(pCurve2d->GetEndPoint(), 0), endPt, false, &endParam, endMinDistance);
    if (!success1 || !success2 || !success3)
        return false;

    if (pSurfaceAndTerminals->HasLocalTerminalParams(modelviewId))
    {
        TerminalParams params = pSurfaceAndTerminals->GetLocalTerminalParams(modelviewId);
        params.SetStartRangeU(startParam.GetX());
        params.SetMidRangeU(midParam.GetX());
        params.SetEndRangeU(endParam.GetX());
        pSurfaceAndTerminals->AddOrUpdateLocalTerminalParams(modelviewId, params);

        OutputDebugString(params.GetRangeUDebugString().c_str());
    }
    else
    {
        TerminalParams params = pSurfaceAndTerminals->GetGlobalTerminalParams();
        params.SetStartRangeU(startParam.GetX());
        params.SetMidRangeU(midParam.GetX());
        params.SetEndRangeU(endParam.GetX());
        pSurfaceAndTerminals->SetGlobalTerminalParams(params);

        OutputDebugString(params.GetRangeUDebugString().c_str());
    }

    return true;
}

REGISTER_IMPLEMENTATION_UID_TREE_RELATION(IGenericElement, SingleGrid);

